import Utils from './utils'
import CreatePlayer from './createPlayer'
import CreateRecorder from './createRecorder'
import ProgressBar from './progressbar';
import ControlPanel from './controlpanel';
import Dialog from './dialog';
import Config from './config'
/**
 * 初始化aipanel实例的默认值。<br/>
 *
 * @global
 * @constant
 * @property {string} server - 指定SDK的评分服务器地址。默认值: ws://cloud.chivox.com
 * @property {string} appKey - 指定SDK的开始评分所使用的appKey（由驰声提供）。**必填**
 * @property {string} sigurl - 指定SDK的开始评分前获取sig和timestamp的服务器地址（sig算法由驰声提供）。**必填**
 * @property {boolean} recorder - 是否创建录音机。
 * @property {boolean} player - 是否创建播放器。
 * @property {boolean} playDing - 录音前，是否播放"Ding"音频。
 * @property {boolean} logbus - 是否发送logbus日志 (默认值：true,发送)。
 * @property {Object} data - 录音和播放音频所需的参数列表，如下：
 * @property {Object} data.audioUrl - 播放的音频URL。
 * @property {Object} data.playPosition {int} 播放开始时间点(ms)<br>
 * @property {Object} data.playDuration {int} 播放持续时间(ms)，取值必须大于500<br>
 * @property {Object} data.serverParams - 录音所需的参数列表，下面描述几个基本的，更多请参考Example或联系驰声提供。
 * @property {Object} data.serverParams.coreType - 录音使用的内核类型。
 * @property {Object} data.serverParams.refText - 录音使用的参考文本。
 * @property {Object} data.serverParams.rank - 录音使用的分制。
 * @property {Object} data.serverParams.userId - 录音的终端用户ID，用于统计和分析用户更多的数据。
 * @property {callback} onInit - SDK初始化完成后的Callback调用。格式：(data) => {}
 * @property {callback} onError - SDK初始化或运行期间出错时的Callback调用。格式：(error) => {}
 * @property {callback} onConnectorStatusChange - SDK在与服务器的连接状态发生变化时的Callback调用。格式：(data) => {}
 * @property {callback} onAfterPlay - 开始播放音频后的Callback调用。格式：(element) => {}
 * @property {callback} onBeforeRecord - 开始录音前的Callback调用。格式：() => {}
 * @property {callback} onScore - 评分结果返回时的Callback调用。格式：(data) => {}
 * @property {callback} onInternalScore- 段落评分时实时push下来当前句子评测结果时的Callback调用。格式：(data) => {}
 * @property {callback} onScoreError - 评分结果返回时的Callback调用。格式：(errorType) => {}
 *
 */
const Default_AiPanel_Options = {
    appKey:"",
    sigurl: "",
    server:  "ws://" + Config.server,
    micWatch:false,
    recorder: true,
    player: true,
    playDing: true,
    logbus:true,
    getResult:false,
    data: {},
    onInit: (errno, err) => {},
    onError: (err) => {},
    onInitSuccess:null,
    onConnectorStatusChange: (code, message) => {
        Utils.log('[ onConnectorStatusChange ]', code, message);
    }

};
const AiPanel_Dialog = null;

class AiPanel {
    constructor(options){
        this.options = Utils.extend(options,Default_AiPanel_Options,true);
        this._recorder_disabled = true;

        this._AiPanel_status = false;
        this.progressbar = new ProgressBar(); //录音进度条
        this.controlpanel = new ControlPanel(); //播放,回放,录音控制面板
        if(!AiPanel_Dialog){
           // this.dialog = new Dialog();
        }
        if(this.options.player){
            this.player = AiPanel.createPlayer(this.options);
            this.bindPlayerEvent();
        }

        if(this.options.recorder){
            this.recorder = AiPanel.createRecorder(this.options,(err) => {
                this._recorder_disabled = true;
                if(err.hasOwnProperty("tokenId")){
                    if(this.options.getResult === false && this.lastTokenId == err.tokenId){
                        this.options.onError(err);
                    }else if(this.options.getResult === true){
                        this.options.onError(err);
                    }
                }else{
                    this.options.onError(err);
                }

            });
            this.bindRecorderEvent();
            this.bindReplayEvent();
        }
        this._AiPanel_status = true;
    }

    /** 为SDK实例绑定播放事件*/
    bindPlayerEvent() {
        this.controlpanel.playOff();

        if (!this.player) {
            Utils.log('no player for the instance. ');
            return;
        }

        if (!this.controlpanel.ele_plays) {
            console.warn('not found any play button in aiPanell');
            return;
        }

        Utils.bind_mul(this.controlpanel.ele_plays, 'click', (ev) => {
            if (!this._AiPanel_status) {
                console.warn('SDK initialization has not been completed yet!');
                return;
            }

            let e = ev || window.event;
            let ele_play = e.target || e.srcElement;

            if (!this.player.can_play) {
                this.controlpanel.playOff();
                return;
            }

            if (Utils.hasClass(ele_play, 'playOn')) {
                this.controlpanel.playOff(ele_play);
                this.player.reset();
            } else {
                this.resetStatus(ele_play, null, null);
                this.controlpanel.playOn(ele_play);

                if (this.options.onBeforePlay) {
                    this.options.onBeforePlay(ele_play);
                }

                this.player.load({
                    url: this.options.data.audioUrl,
                    success: (code, mesage) => {
                        if (Utils.hasClass(ele_play, 'playOn')) {
                            this.player.play({
                                position: this.options.data.playPosition,
                                duration: this.options.data.playDuration,
                                onStart: (code, message) => {},
                                onStop: (code, message) => {
                                    this.controlpanel.playOff(ele_play);
                                    if (typeof this.options.onAfterPlay == 'function')
                                        this.options.onAfterPlay(ele_play);
                                }
                            });
                        } else {
                            console.warn('play button has no class : playOn.');
                        }
                    }
                });
            }
        });
    }

    /** 为SDK实例绑定录音事件*/
    bindRecorderEvent(){
        this.controlpanel.recordOff();
        if (!this.recorder) {
            Utils.log('no recorder for the instance. ');
            return;
        }

        Utils.bind_mul(this.controlpanel.ele_records, 'click', (ev) => {
            if (!this._AiPanel_status) {
                console.warn('SDK initialization has not been completed yet!');
                return;
            }

            let e = ev || window.event;
            let ele_record = e.target || e.srcElement;

            if (!this._recorder_disabled) {
                return;
            }
            if (Utils.hasClass(ele_record, 'recordOff')) {
                this.lastTokenId = "";
                ele_record.setAttribute('dataRecordId', '');

                if (this.options.onBeforeRecord) {
                    this.options.onBeforeRecord(ele_record);
                }

                this.resetStatus(null, ele_record, null);
                this._recorder_disabled = false;
                this.recorder.record({
                    duration: this.options.data.duration,
                    playDing: this.options.playDing,
                    audioType:this.options.data.audioType,
                    logbus: this.options.logbus,
                    serverParams: this.options.data.serverParams,
                    onRecordIdGenerated: (tokenId) => {
                        if(tokenId){
                            this.lastTokenId = tokenId.tokenId;
                            ele_record.setAttribute('dataRecordId', tokenId.tokenId);
                            if(typeof this.options.onRecordIdGenerated == "function"){
                                this.options.onRecordIdGenerated(tokenId)
                            }
                        }
                    },
                    onStart: () => {
                        this._recorder_disabled = true;
                        this.controlpanel.recordOn(ele_record);
                        let idx = ele_record.getAttribute('dataIndex');
                        if (idx) idx = parseInt(idx);
                        let duration =  this._comDuration();
                        this.progressbar.start(duration, idx);
                        if(typeof this.options.onStartRecord == "function"){
                            this.options.onStartRecord();
                        }
                    },
                    onStop: () => {
                        this.controlpanel.recordOff(ele_record);
                        this.progressbar.stop();
                        if(typeof this.options.onAfterRecord == "function"){
                            this.options.onAfterRecord(ele_record);
                        }
                    },
                    onInternalScore: (json) => {
                        if (this.options.onInternalScore)
                            this.options.onInternalScore(json);
                    },
                    onScore: (data) =>{
                        if(this.options.getResult === false && this.lastTokenId == data.tokenId){
                            if (typeof this.options.onScore == "function"){
                                this.options.onScore(data);
                            }
                        }else if(this.options.getResult === true){
                            if (typeof this.options.onScore == "function"){
                                this.options.onScore(data);
                            }
                        }
                    },
                    onScoreError: (data) => {
                        this._recorder_disabled = true;
                        if(this.options.getResult === false && this.lastTokenId == data.tokenId){
                            if(typeof  this.options.onScoreError == "function"){
                                this.options.onScoreError(data)
                            }
                        }else if(this.options.getResult === true){
                            if(typeof  this.options.onScoreError == "function"){
                                this.options.onScoreError(data)
                            }
                        }
                    },
                    onFrame: (data) =>{
                        if(typeof this.options.onFrame === "function"){
                            this.options.onFrame(data);
                        }
                    }
                });
            } else {    // stoprecord
                this.controlpanel.recordOff(ele_record);
                this.progressbar.stop();
                this.recorder.stopRecord();
            }
        });
    }

    /** 为SDK实例绑定录音回放事件。*/
    bindReplayEvent() {
        this.controlpanel.replayDisabled();

        Utils.bind_mul(this.controlpanel.ele_replays, 'click', (ev) => {
            if (!this._AiPanel_status) {
                console.warn('SDK initialization has not been completed yet!');
                return;
            }

            let e = ev || window.event;
            let ele_replay = e.target || e.srcElement;

            if (this.recorder._status !== Utils.Status.completed && this.recorder._status !== Utils.Status.recording) {
                this.controlpanel.recordOff();
                this.controlpanel.replayDisabled();
               // this.dialog.open();
                return;
            }

            if (!Utils.hasClass(ele_replay, 'replayDisabled')) {
                var token_id = this.lastTokenId;

                if (token_id != '') {
                    if (Utils.hasClass(ele_replay, 'replayOff')) {
                        this.resetStatus(null, null, ele_replay);
                        if(typeof this.options.onBeforeReplay == "function"){
                            this.options.onBeforeReplay(ele_replay);
                        }

                        this.controlpanel.replayOn(ele_replay);

                        this.recorder.startReplay({
                            onStop: () => {
                                this.controlpanel.replayOff(ele_replay);
                                if(typeof this.options.onAfterReplay == "function"){
                                    this.controlpanel.replayOff(ele_replay);
                                    this.options.onAfterReplay(ele_replay);
                                }
                            }
                        });
                    } else {
                        this.controlpanel.replayOff(ele_replay);
                        this.recorder.stopReplay();
                    }
                }
            }
        });
    }

     _comDuration(){
        let duration = 2000;
        let core_type = this.options.data.serverParams.coreType;
        if (typeof this.options.data.duration == "number"){
            duration =  this.options.data.duration >= 2000 ? this.options.data.duration : duration;
        } else{
            if (Utils.in_array(core_type, ['cn.word.score', 'cn.sent.score'])) {
                let reftxt_cnt = this.options.data.serverParams.refText.replace(/^\s+|\s+$/g, '').split('-').length;
                duration = 2000 + reftxt_cnt * 600;
            } else if (Utils.in_array(core_type, ['en.word.score', 'en.sent.score'])) {
                let reftxt_cnt = this.options.data.serverParams.refText.replace(/^\s+|\s+$/g, '').split(' ').length;
                duration = 2000 + reftxt_cnt * 600;
            }else if(Utils.in_array(core_type, [ 'en.pred.exam'])){
                let reftxt_cnt = 0;
                if(this.options.data.serverParams.refText.hasOwnProperty('lm')){
                    reftxt_cnt = this.options.data.serverParams.refText.lm.match(/[a-zA-Z]+/ig).length
                }else{
                    reftxt_cnt = this.options.data.serverParams.refText.replace(/^\s+|\s+$/g, '').split(' ').length;
                }
                duration = 2000 + reftxt_cnt * 600;
            }
        }
        return duration

    }


    /**
     * 创建录音机。
     *
     * @param {Object} options - 创建录音机所需要的参数。
     * @return {Object} - Recorder的实例。
     */
    static createRecorder (options,complete){
        return CreateRecorder.build(options,complete);
    }

    /**
     * 创建播放器。
     *
     * @param {Object} options - 创建播放器所需要的参数。
     * @return {Object} - Player的实例。
     */

    static createPlayer (options){
        return CreatePlayer.build(options);
    }


    /**
     * rebind 页面节点改变后，重新绑定事件接口
     * */
    rebind(){
        this.bindPlayerEvent();
        this.bindRecorderEvent();
        this.bindReplayEvent();
    }


    /**
     * 重置SDK实例接口。
     * */
    resetStatus(ele_play, ele_record, ele_replay) {

        if (this.recorder){
            if(ele_record){
                this.recorder.stopRecord();
            }else{
                this.recorder.reset();
            }
        }

        if (this.player)
            this.player.reset();
        this._recorder_disabled = true;
        this.progressbar.reset();
        this.controlpanel.playOff();
        this.controlpanel.recordOff();
        this.controlpanel.replayOff();

        if (typeof ele_play == 'undefined' && typeof ele_record == 'undefined' && typeof ele_replay == 'undefined') {
            this.controlpanel.replayDisabled();
        }
    }
    /**
     * SDK实例更新或设置data参数接口。
     * options.data内所有参数都可以重新设置
     * */
    setData(data) {
        this.resetStatus();
        if(data && typeof data === "object"){
            this.options.data = data;
        }else{
            console.error("data is invalid");
        }
    }

    /**
     * 是否显示or获取频谱接口
     * @params - {function} 接收返回频谱数据回调
     * */
    showVolumeBar(callback){
        if (this.recorder){
            this.recorder.showVolumeBar(callback);
        }
    }

    /**
     * 销毁audioContext上下文接口
     * */
    dispose(){
        if (this.player && this.player.ctx) {
           this.player.dispose();
        }

        if (this.recorder && this.recorder.context) {
           this.recorder.dispose();
        }
    }

}
window.ChiVoxSDK = AiPanel;
export default AiPanel;


